/*
 * Copyright (C) 2017-2021
 * All rights reserved, Designed By
 * Copyright authorization contact 18814114118
 */
package com.shop.cereshop.business.service.bond.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.shop.cereshop.business.dao.bond.CereShopBondDAO;
import com.shop.cereshop.business.dao.bond.CereShopBondRechargeDAO;
import com.shop.cereshop.business.page.bond.ShopRechargeVO;
import com.shop.cereshop.business.param.bond.ShopRechargeDTO;
import com.shop.cereshop.business.service.bond.CereShopBondRechargeService;
import com.shop.cereshop.business.service.bond.CereShopBondService;
import com.shop.cereshop.commons.constant.BondConstant;
import com.shop.cereshop.commons.constant.BondConstant;
import com.shop.cereshop.commons.domain.bond.CereShopBondRecharge;
import com.shop.cereshop.commons.utils.TimeUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
@RequiredArgsConstructor
public class CereShopBondRechargeServiceImpl extends ServiceImpl<CereShopBondRechargeDAO, CereShopBondRecharge>
    implements CereShopBondRechargeService {

  private final CereShopBondRechargeDAO cereShopBondRechargeDAO;

  private final CereShopBondDAO cereShopBondDAO;

  private final CereShopBondService cereShopBondService;

  @Override
  public List<CereShopBondRecharge> getRechargeList(Long shopId, Integer page, Integer pageSize) {
      try {
          //设置分页参数
          PageHelper.startPage(page, pageSize);

          //查询充值记录
          List<CereShopBondRecharge> rechargeList = cereShopBondRechargeDAO.getRechargeList(shopId);

          log.info("查询用户{}充值记录，页码：{}，每页大小：{}，结果数量：{}",
                  shopId, page, pageSize, rechargeList.size());
          return rechargeList;
      } catch (Exception e) {
          log.error("查询店铺充值记录失败，店铺id:{}", shopId, e);
          throw e;
      }
  }

    @Override
  public ShopRechargeVO createRechargeOrder (ShopRechargeDTO param){
      try {
          //验证充值金额
          if (param.getAmount().compareTo(new BigDecimal(BondConstant.WalletConfig.MIN_RECHARGE_AMOUNT)) < 0) {
              throw new IllegalArgumentException("充值金额不能少于" + BondConstant.WalletConfig.MIN_RECHARGE_AMOUNT + "元");
          }
          if (param.getAmount().compareTo(new BigDecimal(BondConstant.WalletConfig.MAX_RECHARGE_AMOUNT)) > 0) {
              throw new IllegalArgumentException("充值金额不能大于" + BondConstant.WalletConfig.MAX_RECHARGE_AMOUNT + "元");
          }

          //生成充值单号
          String rechargeNo = generateRechargeNo();

          //查询店铺对应的保证金id
          Long bondId = cereShopBondDAO.getShopBondId(param.getShopId());

          //当前时间
          LocalDateTime now = LocalDateTime.now();

          //计算过期时间
          LocalDateTime expireTime = LocalDateTime.now().plusMinutes(BondConstant.WalletConfig.RECHARGE_EXPIRE_MINUTES);

          //创建充值记录
          CereShopBondRecharge cereShopBondRecharge = new CereShopBondRecharge();
          cereShopBondRecharge.setShopId(param.getShopId())
                  .setRemark(param.getRemark())
                  .setBondId(bondId)
                  .setRechargeNo(rechargeNo)
                  .setAmount(param.getAmount())
                  .setPayType(param.getPayType())
                  .setPayState(BondConstant.PayState.PENDING)
                  .setExpireTime(expireTime)
                  .setCreateTime(now)
                  .setUpdateTime(now);

          //保存充值记录
          cereShopBondRechargeDAO.insert(cereShopBondRecharge);

          //构建返回值
          ShopRechargeVO shopRechargeVO = new ShopRechargeVO();
          shopRechargeVO
                  .setRechargeId(cereShopBondRecharge.getRechargeId())
                  .setRechargeNo(cereShopBondRecharge.getRechargeNo())
                  .setAmount(cereShopBondRecharge.getAmount())
                  .setPayType(cereShopBondRecharge.getPayType())
                  .setPayState(cereShopBondRecharge.getPayState())
                  .setExpireTime(cereShopBondRecharge.getExpireTime())
                  .setCreateTime(cereShopBondRecharge.getCreateTime());

          // TODO: 根据支付方式生成支付参数
          // 这里先返回空，后续根据具体支付方式实现
          shopRechargeVO.setPayParams("{}");
          shopRechargeVO.setPayUrl("");

          log.info("店铺{}创建充值订单成功，单号：{}，金额：{}", param.getShopId(), rechargeNo, param.getAmount());
          return shopRechargeVO;
      } catch (Exception e) {
          log.error("创建充值订单失败，店铺ID：{}，金额：{}", param.getShopId(), param.getAmount(), e);
          throw e;
      }
  }

   @Override
  public CereShopBondRecharge getRechargeDetail(String rechargeNo) {
      try {
          CereShopBondRecharge shopBondRecharge = cereShopBondRechargeDAO.selectByRechargeNo(rechargeNo);
          if (shopBondRecharge != null) {
              log.info("查询充值详情成功，单号：{}", rechargeNo);
          } else {
              log.warn("充值记录不存在，单号：{}", rechargeNo);
          }
          return shopBondRecharge;
      } catch (Exception e) {
          log.error("查询充值详情失败，单号：{}", rechargeNo, e);
          return null;
      }
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean cancelRechargeOrder(String rechargeNo, Long shopId) {
      try {
          CereShopBondRecharge shopBondRecharge = cereShopBondRechargeDAO.selectByRechargeNo(rechargeNo);
          if (shopBondRecharge == null) {
              log.warn("充值记录不存在，单号:{}", rechargeNo);
              return false;
          }

          //验证用户权限
          if (!shopId.equals(shopBondRecharge.getShopId())) {
              log.warn("用户无权限操作充值记录，店铺ID:{}，单号:{}", shopId, rechargeNo);
              return false;
          }

          //检查充值状态
          if (!BondConstant.PayState.PENDING.equals(shopBondRecharge.getPayState())) {
              log.warn("充值订单状态错误，单号:{}，状态:{}", rechargeNo, shopBondRecharge.getPayState());
              return false;
          }

          //更新充值状态
          int result = cereShopBondRechargeDAO.updatePayState(rechargeNo, BondConstant.PayState.CANCELLED, null, null);

          if (result > 0) {
              log.info("取消充值订单成功，单号:{},店铺id:{}", rechargeNo, shopId);
              return true;
          } else {
              log.warn("取消充值订单失败，单号:{}, 店铺id:{}", rechargeNo, shopId);
              return false;
          }
      } catch (Exception e) {
          log.error("取消充值订单失败，单号:{}", rechargeNo, e);
          return false;
      }
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean handleRechargeSuccess(String rechargeNo, String thirdPartyOrderNo) {
      //1、查询充值记录
      CereShopBondRecharge shopBondRecharge = cereShopBondRechargeDAO.selectByRechargeNo(rechargeNo);
      if (shopBondRecharge == null) {
          log.warn("充值记录不存在，单号:{}", rechargeNo);
          return false;
      }

      //2、检查充值状态
      if (!BondConstant.PayState.PENDING.equals(shopBondRecharge.getPayState())) {
          log.warn("充值订单状态错误，单号:{}，状态:{}", rechargeNo, shopBondRecharge.getPayState());
          return false;
      }

      //3、更新充值状态
      LocalDateTime now = LocalDateTime.now();
      int result = cereShopBondRechargeDAO.updatePayState(rechargeNo,
              BondConstant.PayState.SUCCESS,
              thirdPartyOrderNo,
              now);

      if (result > 0) {
          //更新保证金余额
          boolean walletUpdated = cereShopBondService.updateBalance(
                  shopBondRecharge.getShopId(),
                  shopBondRecharge.getAmount(),
                  BondConstant.TransactionType.RECHARGE,
                  rechargeNo,
                  "钱包充值"
                  );

          if (walletUpdated) {
              log.info("充值成功处理完成，单号：{}，店铺：{}，金额：{}",
                  rechargeNo, shopBondRecharge.getShopId(), shopBondRecharge.getAmount());
              return true;
          } else {
              log.warn("充值成功处理失败，单号：{}，店铺：{}，金额：{}",
                  rechargeNo, shopBondRecharge.getShopId(), shopBondRecharge.getAmount());
              return false;
          }
      }
      return false;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean handleRechargeFail(String rechargeNo, String failReason) {
      try {
          //1、查询充值记录
          CereShopBondRecharge shopBondRecharge = cereShopBondRechargeDAO.selectByRechargeNo(rechargeNo);
          if (shopBondRecharge == null) {
              log.warn("充值记录不存在，单号:{}", rechargeNo);
              return false;
          }

          //2、更新充值状态
          int result = cereShopBondRechargeDAO.updatePayState(rechargeNo,
                  BondConstant.PayState.FAILED,
                  null,
                  null);

          if (result > 0) {
              log.info("充值失败处理完成，单号：{}，店铺：{}，金额：{}，失败原因：{}",
                  rechargeNo, shopBondRecharge.getShopId(), shopBondRecharge.getAmount(), failReason);
              return true;
          }
          return false;
      } catch (Exception e) {
          log.error("充值失败处理失败，单号：{}", rechargeNo, e);
          return false;
      }
  }

    @Override
    public CereShopBondRecharge getDetailById(Long rechargeId) {
        return cereShopBondRechargeDAO.selectById(rechargeId);
    }

    /**
   * 生成充值单号
   * @return 充值单号
   */
  private String generateRechargeNo() {
      return "RC" + TimeUtils.todayTime() + UUID.randomUUID().toString().replace("-", "").substring(0, 8);
  }
}